package sh

import (
	"context"
	"fmt"
	"os/exec"
	"runtime"
	"time"
)

// Run linux通过sh来运行shell命令, windows通过cmd运行shell命令
func Run(shell string, timeout ...int) (string, error){
	switch runtime.GOOS {
	case "windows":
		return runWindowsShell(shell, timeout...)
	case "linux","darwin":
		return runLinuxShell(shell, timeout...)
	}
	return "", fmt.Errorf("不支持的Os: %v", runtime.GOOS)
}

func runWindowsShell(shell string, timeout ...int) (string, error) {
	var out = 60000
	if len(timeout) > 0 {
		out = timeout[0]
	}
	if out < 0 {
		out = 0
	}
	ctx, _ := context.WithTimeout(context.Background(), time.Duration(out)*time.Millisecond)
	cmd := exec.CommandContext(ctx, "cmd", "/c", shell)
	// cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	return runCmd(cmd)
}

func runLinuxShell(shell string, timeout ...int) (string, error) {
	var out = 60000
	if len(timeout) > 0 {
		out = timeout[0]
	}
	if out < 0 {
		out = 0
	}
	ctx, _ := context.WithTimeout(context.Background(), time.Duration(out)*time.Millisecond)
	cmd := exec.CommandContext(ctx, "sh", "-c", shell)
	return runCmd(cmd)
}

func runCmd(cmd *exec.Cmd) (string, error) {
	os, err := cmd.Output()
	if err != nil {
		if e, ok := err.(*exec.ExitError); !ok {
			return "", fmt.Errorf("runCmd[%v]\n%w", cmd.Args, err)
		} else {
			if e.ExitCode() != 0 {
				return "", fmt.Errorf("%v\n%w", string(e.Stderr), e)
			}
			return string(os), nil
		}
	}
	// r := localereader.NewReader(bytes.NewBuffer(os))
	// nos, _ := ioutil.ReadAll(r)
	// todo 如果是在中文windows下, 默认编码是gbk, 直接转string会乱码
	// 可以通过https://github.com/Xuanwo/go-locale这个库来获取系统的编码, 但是感觉用的不多, 所以暂时先不加上这段解码的
	return string(os), nil
}